#include"http.hpp"


#define WWWROOT "./wwwroot/"

std::string RequestStr(const HttpRequest &req)
{
    std::stringstream ss;
    ss<<req._method<<" "<<req._path<<" "<<req._version<<"\r\n";
    for(auto &it:req._params)
    {
        ss<<it.first<<": "<<it.second<<"\r\n";
    }
    for(auto &it:req._headers)
    {
        ss<<it.first<<": "<<it.second<<"\r\n";
    }
    ss<<"\r\n";
    ss<<req._body;
    return ss.str();

}
void Hello(const HttpRequest &req,HttpResponse *resp)
{
    resp->SetContent(RequestStr(req),"text/plain");
}
void Login(const HttpRequest &req,HttpResponse *resp)
{
    resp->SetContent(RequestStr(req),"text/plain");
}
void PutFile(const HttpRequest &req,HttpResponse *resp)
{
    std::string path = WWWROOT+req._path;
    Util::WriteFile(path,req._body);/*向请求正文中请求path资源路径的正文*/
}
void DelFile(const HttpRequest &req,HttpResponse *resp)
{
    resp->SetContent(RequestStr(req),"text/plain");
}
int main()
{
    HttpServer server(8005);
    server.SetThreadCount(3);
    server.SetBaseDir(WWWROOT);/*设置静态资源根目录，告诉服务器有静态资源请求到来，需要到哪找资源文件*/
    server.Get("/hello",Hello);
    server.Post("/login",Login);
    server.Put("/1234.txt",PutFile);
    server.Delete("/1234.txt",DelFile);
    server.Listen();
    return 0;
}

















// ssize_t Split(const std::string &src,const std::string &sep,std::vector<std::string> *array)
// {
//     ssize_t offset = 0;
//     while(offset < src.size())
//     {
//         ssize_t pos = src.find(sep,offset);//从偏移量offset处开始向后查找sep字符/字符串，返回查找到的位置
//         if(pos == std::string::npos)
//         {
//             if(pos==src.size()) break;
//             //找不到，说明是剩余部分就是需要的子串
//             array->push_back(src.substr(offset));
//             return array->size();
//         }
//         if(pos != offset) array->push_back(src.substr(offset,pos-offset));
//         offset = pos+sep.size();
//     }
//     return array->size();
// }


// //读取文件的所有内容，放到Buffer中
// static bool ReadFile(std::string filename, std::string *buf)
// {
//     //使用std::ifstream打开指定文件名的文件，以二进制模式读取
//     std::ifstream ifs(filename, std::ios::binary);

//     //检查文件是否成功打开
//     if (ifs.is_open() == false)
//     {
//         //如果文件未打开，输出错误日志并返回false
//         ERR_LOG("open %s file failed!", filename.c_str());
//         return false;
//     }

//     //获取文件大小
//     size_t fsize = 0;
//     ifs.seekg(0, ifs.end); //移动文件流到文件末尾
//     fsize = ifs.tellg();   //获取当前文件位置，即文件大小
//     ifs.seekg(0, ifs.beg); //将文件流重新定位到文件开头
//     buf->resize(fsize);    //开辟文件大小的空间
//     //从文件中读取数据到字符串str中
//     ifs.read(&(*buf)[0], fsize);

//     //检查文件读取是否成功
//     if (ifs.good() == false)
//     {
//         //如果文件读取失败，输出错误日志，关闭文件流并返回false
//         ERR_LOG("READ %s FILE FAILED!", filename.c_str());
//         ifs.close();
//         return false;
//     }
//     ifs.close();
//     return true;
// }

// //向文件写入数据
// static bool WriteFile(const std::string filename, const std::string *buf)
// {
//     std::ofstream ofs(filename,std::ios::binary | std::ios::trunc);
//     if(ofs.is_open() == false)
//     {
//         ERR_LOG("OPEN %s FILE FAILED!",filename.c_str());
//         return false;
//     }
//     ofs.write(buf->c_str(),buf->size());
//     if(ofs.good()==false)
//     {
//         ERR_LOG("WRITE %s FILE FAILED!",filename.c_str());
//         ofs.close();
//         return false;
//     }
//     ofs.close();
//     return true;

// }

// static std::string UrlEncode(const std::string url,bool conver_space_to_plus)
// {
//     std::string res;
//     for(auto &c:url)
//     {
//         if(c=='.' || c=='-' || c=='~' || isalnum(c))
//         {
//             res+=c;
//             continue;
//         }

//         if(c==' ' && conver_space_to_plus==true)
//         {
//             res+='+';
//             continue;
//         }
//         //剩下的字符都是需要编码为%HH的格式
//         char tmp[4]={0};
//         snprintf(tmp,4,"%%%02X",c);
//         res+=tmp;
//     }
//     return res;
// }
// static char HEXTOI(char c)
// {
//     if(c >= '0' && c<='9') return c-'0';
//     else if(c >= 'a' && c <= 'z') return c-'a'+10;
//     else if(c >= 'A' && c <= 'Z') return c-'A'+10;
//     return -1;
// }
// static std::string UrlDecode(const std::string url,bool conver_plus_to_space)
// {
//     std::string res;
//     for(int i = 0;i<url.size();++i)
//     {
//         if(url[i]=='+' && conver_plus_to_space==true)
//         {
//             res+=' ';
//             continue;
//         }
//         if(url[i]=='%')
//         {
//             char v1 = HEXTOI(url[i+1]);
//             char v2 = HEXTOI(url[i+2]);
//             char v = v1 *16+v2;
//             res+=v;
//             i+=2;
//             continue;
//         }
//         res+=url[i];
//     }
//     return res;
// }

// static std::string StatuDesc(int statu)
// {
//     std::unordered_map<int,std::string> _statu_msg = {
//         {100,  "Continue"},
//         {101,  "Switching Protocol"},
//         {102,  "Processing"},
//         {103,  "Early Hints"},
//         {200,  "OK"},
//         {201,  "Created"},
//         {202,  "Accepted"},
//         {203,  "Non-Authoritative Information"},
//         {204,  "No Content"},
//         {205,  "Reset Content"},
//         {206,  "Partial Content"},
//         {207,  "Multi-Status"},
//         {208,  "Already Reported"},
//         {226,  "IM Used"},
//         {300,  "Multiple Choice"},
//         {301,  "Moved Permanently"},
//         {302,  "Found"},
//         {303,  "See Other"},
//         {304,  "Not Modified"},
//         {305,  "Use Proxy"},
//         {306,  "unused"},
//         {307,  "Temporary Redirect"},
//         {308,  "Permanent Redirect"},
//         {400,  "Bad Request"},
//         {401,  "Unauthorized"},
//         {402,  "Payment Required"},
//         {403,  "Forbidden"},
//         {404,  "Not Found"},
//         {405,  "Method Not Allowed"},
//         {406,  "Not Acceptable"},
//         {407,  "Proxy Authentication Required"},
//         {408,  "Request Timeout"},
//         {409,  "Conflict"},
//         {410,  "Gone"},
//         {411,  "Length Required"},
//         {412,  "Precondition Failed"},
//         {413,  "Payload Too Large"},
//         {414,  "URI Too Long"},
//         {415,  "Unsupported Media Type"},
//         {416,  "Range Not Satisfiable"},
//         {417,  "Expectation Failed"},
//         {418,  "I'm a teapot"},
//         {421,  "Misdirected Request"},
//         {422,  "Unprocessable Entity"},
//         {423,  "Locked"},
//         {424,  "Failed Dependency"},
//         {425,  "Too Early"},
//         {426,  "Upgrade Required"},
//         {428,  "Precondition Required"},
//         {429,  "Too Many Requests"},
//         {431,  "Request Header Fields Too Large"},
//         {451,  "Unavailable For Legal Reasons"},
//         {501,  "Not Implemented"},
//         {502,  "Bad Gateway"},
//         {503,  "Service Unavailable"},
//         {504,  "Gateway Timeout"},
//         {505,  "HTTP Version Not Supported"},
//         {506,  "Variant Also Negotiates"},
//         {507,  "Insufficient Storage"},
//         {508,  "Loop Detected"},
//         {510,  "Not Extended"},
//         {511,  "Network Authentication Required"} 
//     };
//     auto it = _statu_msg.find(statu);
//     if(it != _statu_msg.end())
//     {
//         return it->second;
//     }
//     return "Unknow";
// }

// static std::string ExtMime(const std::string &filename)
// {
//     std::unordered_map<std::string,std::string> _mime_msg = {
//         {".aac",        "audio/aac"},
//         {".abw",        "application/x-abiword"},
//         {".arc",        "application/x-freearc"},
//         {".avi",        "video/x-msvideo"},
//         {".azw",        "application/vnd.amazon.ebook"},
//         {".bin",        "application/octet-stream"},
//         {".bmp",        "image/bmp"},
//         {".bz",         "application/x-bzip"},
//         {".bz2",        "application/x-bzip2"},
//         {".csh",        "application/x-csh"},
//         {".css",        "text/css"},
//         {".csv",        "text/csv"},
//         {".doc",        "application/msword"},
//         {".docx",       "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
//         {".eot",        "application/vnd.ms-fontobject"},
//         {".epub",       "application/epub+zip"},
//         {".gif",        "image/gif"},
//         {".htm",        "text/html"},
//         {".html",       "text/html"},
//         {".ico",        "image/vnd.microsoft.icon"},
//         {".ics",        "text/calendar"},
//         {".jar",        "application/java-archive"},
//         {".jpeg",       "image/jpeg"},
//         {".jpg",        "image/jpeg"},
//         {".js",         "text/javascript"},
//         {".json",       "application/json"},
//         {".jsonld",     "application/ld+json"},
//         {".mid",        "audio/midi"},
//         {".midi",       "audio/x-midi"},
//         {".mjs",        "text/javascript"},
//         {".mp3",        "audio/mpeg"},
//         {".mpeg",       "video/mpeg"},
//         {".mpkg",       "application/vnd.apple.installer+xml"},
//         {".odp",        "application/vnd.oasis.opendocument.presentation"},
//         {".ods",        "application/vnd.oasis.opendocument.spreadsheet"},
//         {".odt",        "application/vnd.oasis.opendocument.text"},
//         {".oga",        "audio/ogg"},
//         {".ogv",        "video/ogg"},
//         {".ogx",        "application/ogg"},
//         {".otf",        "font/otf"},
//         {".png",        "image/png"},
//         {".pdf",        "application/pdf"},
//         {".ppt",        "application/vnd.ms-powerpoint"},
//         {".pptx",       "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
//         {".rar",        "application/x-rar-compressed"},
//         {".rtf",        "application/rtf"},
//         {".sh",         "application/x-sh"},
//         {".svg",        "image/svg+xml"},
//         {".swf",        "application/x-shockwave-flash"},
//         {".tar",        "application/x-tar"},
//         {".tif",        "image/tiff"},
//         {".tiff",       "image/tiff"},
//         {".ttf",        "font/ttf"},
//         {".txt",        "text/plain"},
//         {".vsd",        "application/vnd.visio"},
//         {".wav",        "audio/wav"},
//         {".weba",       "audio/webm"},
//         {".webm",       "video/webm"},
//         {".webp",       "image/webp"},
//         {".woff",       "font/woff"},
//         {".woff2",      "font/woff2"},
//         {".xhtml",      "application/xhtml+xml"},
//         {".xls",        "application/vnd.ms-excel"},
//         {".xlsx",       "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
//         {".xml",        "application/xml"},
//         {".xul",        "application/vnd.mozilla.xul+xml"},
//         {".zip",        "application/zip"},
//         {".3gp",        "video/3gpp"},
//         {".3g2",        "video/3gpp2"},
//         {".7z",         "application/x-7z-compressed"}
//     };
//     /*a.b.txt*/
//     /*先获取文件拓展名*/
//     size_t pos = filename.find_last_of('.');
//     if(pos==std::string::npos)
//     {
//         return "application/octet-stream";
//     }
//     std::string ext = filename.substr(pos);
//     /*根据拓展名找对应的mime*/
//     auto it = _mime_msg.find(ext);
//     if(it!=_mime_msg.end())
//     {
//         return it->second;
//     }
//     return "application/octet-stream";
// }

// //判断一个文件是否是一个目录
// static bool IsDirectory(const std::string &filename)
// {
//     struct stat st;
//     int ret = stat(filename.c_str(),&st);
//     if(ret < 0)
//     {
//         return false;
//     }
//     return S_ISDIR(st.st_mode);
// }
// //判断一个文件是否是一个普通文件
// static bool IsRegular(const std::string &filename)
// {
//     struct stat st;
//     int ret = stat(filename.c_str(),&st);
//     if(ret < 0)
//     {
//         return false;
//     }
//     return S_ISREG(st.st_mode);
// }


// static bool ValidPath(const std::string &path)
// {   
//     std::vector<std::string> subdir;
//     Split(path,"/",&subdir);
//     int level = 0;
//     for(auto &dir:subdir)
//     {
//         if(dir=="..")
//         {
//             level--;
//             if(level<0) return false;
//             continue;
//         }
//         level++;
//     }
//     return true;
// }
// int main()
// {
    //路径有效性测试
    // std::cout<<ValidPath("/html/../../index.html")<<std::endl;

    //mime测试
    // std::cout<<IsRegular("regex.cpp")<<std::endl;
    // std::cout<<IsRegular("testdir")<<std::endl;
    // std::cout<<IsDirectory("regex.cpp")<<std::endl;
    // std::cout<<IsDirectory("testdir")<<std::endl;

    // std::string file = "a.vb..woff";
    // std::cout<<ExtMime(file)<<std::endl;
    /*statu测试*/
    // int statu;
    // std::cin>>statu;
    // std::cout<<StatuDesc(statu)<<std::endl;
    //解码测试
    // std::string str="C  ";
    // std::string res = UrlEncode(str,true);
    // std::string temp = UrlDecode(res,true);
    // std::cout<<res<<std::endl;
    // std::cout<<temp<<std::endl;

    //编码测试
    // std::string str="C  ";
    // std::string res;
    // res = UrlEncode(str,true);
    // std::cout<<res<<std::endl;
    //测试写入数据
    // std::string buf;
    // bool ret = ReadFile("../tcpclient.cc",&buf);
    // ret = WriteFile("./ttttt.cc",&buf);
    // std::cout<<buf<<std::endl;

    //读取文件内容测试
    // std::string buf;
    // ReadFile("../tcpclient.cc",&buf);
    // std::cout<<buf<<std::endl;
    /* 字符串分割测试
    std::string src = "abc,,,,,def,ghi,jkl";
    std::vector<std::string> array;
    ssize_t idx = Split(src,",",&array);
    for(auto& c:array)
    {
        std::cout<<"["<<c<<"]\n";
    }*/

//     return 0;
// }